package com.alan.shiro.api.filter;

import com.alan.shiro.api.token.StatelessToken;
import com.alan.shiro.api.token.manager.TokenManager;
import lombok.Getter;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.web.filter.AccessControlFilter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.StringUtils;

import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * @Auther: Alan liu
 * @Date: 2018/12/13 10:04
 * @Description: 无状态授权过滤器
 */
@Slf4j
public class StatelessAuthcFilter extends AccessControlFilter {

    @Setter
    @Getter
    private TokenManager tokenManager;

    @Override
    protected boolean isAccessAllowed(ServletRequest request,
                                      ServletResponse response, Object mappedValue) throws Exception {
        HttpServletRequest httpRequest = (HttpServletRequest) request;
        log.info("isAccessAllowed 拦截到的url:" + httpRequest.getRequestURL().toString());
        // 前段token授权信息放在请求头中传入
        String authorization = ((HttpServletRequest) request).getHeader("authorization");
        if (StringUtils.isEmpty(authorization)) {
            onLoginFail(response, "请求头不包含认证信息authorization");
            return false;
        }
        // 获取无状态Token
        StatelessToken accessToken = tokenManager.getToken(authorization);
        try {
            // 委托给Realm进行登录
            getSubject(request, response).login(accessToken);
        } catch (Exception e) {
            log.error("auth error:" + e.getMessage(), e);
            // 6、登录失败
            onLoginFail(response, "auth error:" + e.getMessage());
            return false;
        }
        // 通过isPermitted 才能调用doGetAuthorizationInfo方法获取权限信息
        getSubject(request, response).isPermitted(httpRequest.getRequestURI());
        return true;
    }

    @Override
    protected boolean onAccessDenied(ServletRequest request,
                                     ServletResponse response) throws Exception {
        log.info("isAccessAllowed");
        return false;
    }

    /**
     * 登录失败时默认返回401状态码
     * @param response
     * @param errorMsg
     * @throws IOException
     */
    private void onLoginFail(ServletResponse response,String errorMsg) throws IOException {
        HttpServletResponse httpResponse = (HttpServletResponse) response;
        httpResponse.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
        httpResponse.setContentType("text/html");
        httpResponse.setCharacterEncoding("utf-8");
        httpResponse.getWriter().write(errorMsg);
        httpResponse.getWriter().close();
    }

}
